#include "seqlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define N 20
typedef struct {
  int id;
  char name[20];
} Student;
int student_cmp(const void *data, const void *key);
void student_print(const void *data);
// 生成了一份测试用的函数
void test();

static void show_int(const void *data);
static int cmp_int(const void *data1, const void *data2);

int main(void) {
  seqlist_t *list = NULL;
  int i;
  int r;

  seqlist_init(&list, sizeof(int), N);

  srand(time(NULL));

  for (i = 0; i < N; i++) {
    r = rand() % 100;
    seqlist_push_back(list, &r);
  }

  seqlist_traval(list, show_int);
  printf("\n");
  seqlist_qsort(list->arr, list->nmemb, list->size, cmp_int);
  seqlist_traval(list, show_int);
  printf("\n");

  seqlist_delete(list, (char *)list->arr, cmp_int);
  seqlist_delete(list, (char *)list->arr + (list->nmemb - 1) * list->size,
                 cmp_int);
  seqlist_traval(list, show_int);
  putchar('\n');

  seqlist_reverse(list);
  seqlist_traval(list, show_int);
  putchar('\n');

  seqlist_destory(&list);
  test();
  return 0;
}

static void show_int(const void *data) {
  const int *d = (const int *)data;
  printf("%d ", *d);
}

static int cmp_int(const void *data1, const void *data2) {
  const int *d1 = (const int *)data1;
  const int *d2 = (const int *)data2;

  return *d1 - *d2;
}
int student_cmp(const void *data, const void *key) {
  const Student *s_data = (const Student *)data;
  const Student *s_key = (const Student *)key;
  return s_data->id - s_key->id;
}

void student_print(const void *data) {
  const Student *s = (const Student *)data;
  printf("ID: %d, Name: %s\n", s->id, s->name);
}

void test() {
  seqlist_t *list = NULL;
  Student stu1 = {101, "Zhang San"}, stu2 = {102, "Li Si"},
          stu3 = {103, "Wang Wu"}, stu4 = {104, "Zhao Liu"},
          find_key = {102, ""}, update_stu = {102, "Li Si (Updated)"};

  printf("==================== 顺序表功能测试 ====================\n");

  // -------------------------- 测试1：初始化顺序表 --------------------------
  printf("\n=== 测试1：初始化顺序表（单个学生大小，初始容量3）===\n");
  int init_ret = seqlist_init(&list, sizeof(Student), 3);
  if (init_ret == 1) {
    printf("初始化成功！当前容量：%d，当前元素数：%d\n", seqlist_capacity(list),
           seqlist_size(list));
  } else {
    printf("初始化失败！\n");
    return;
  }

  // -------------------------- 测试2：尾插元素 --------------------------
  printf("\n=== 测试2：尾插3个学生元素 ===\n");
  seqlist_push_back(list, &stu1);
  seqlist_push_back(list, &stu2);
  seqlist_push_back(list, &stu3);
  printf("尾插后元素数：%d，容量：%d\n", seqlist_size(list),
         seqlist_capacity(list));
  printf("当前元素列表：\n");
  seqlist_traval(list, student_print); // 遍历打印

  // -------------------------- 测试3：指定位置插入（扩容测试）
  // --------------------------
  printf("\n=== 测试3：指定位置插入（索引1，触发扩容）===\n");
  // 此时容量为3，已存3个元素，插入会触发扩容（容量翻倍到6）
  int insert_ret = seqlist_insert(list, 1, &stu4); // 在stu1和stu2之间插入stu4
  if (insert_ret == 1) {
    printf("插入成功！当前元素数：%d，容量：%d\n", seqlist_size(list),
           seqlist_capacity(list));
    printf("插入后元素列表：\n");
    seqlist_traval(list, student_print); // 预期顺序：101 → 104 → 102 → 103
  } else {
    printf("插入失败！\n");
  }

  // -------------------------- 测试4：查找元素（按key + 按索引）
  // --------------------------
  printf("\n=== 测试4：查找元素 ===\n");
  // 4.1 按key查找（查找ID=102的学生）
  Student *find_res =
      (Student *)seqlist_forsearch(list, &find_key, student_cmp);
  if (find_res != NULL) {
    printf("按ID查找（102）成功：");
    student_print(find_res);
  } else {
    printf("按ID查找（102）失败！\n");
  }

  // 4.2 按索引查找（查找索引2的元素，预期是102）
  const Student *get_res = (const Student *)seqlist_get(list, 2);
  if (get_res != NULL) {
    printf("按索引查找（2）成功：");
    student_print(get_res);
  } else {
    printf("按索引查找（2）失败！\n");
  }

  // -------------------------- 测试5：更新元素 --------------------------
  printf("\n=== 测试5：更新元素（ID=102的学生）===\n");
  int update_ret = seqlist_update(list, &find_key, &update_stu, student_cmp);
  if (update_ret == 1) {
    printf("更新成功！更新后ID=102的学生：\n");
    find_res = (Student *)seqlist_forsearch(list, &find_key, student_cmp);
    student_print(find_res);
  } else {
    printf("更新失败！\n");
  }

  // -------------------------- 测试6：删除元素 --------------------------
  printf("\n=== 测试6：删除元素（ID=103的学生）===\n");
  Student del_key = {103, ""};
  int del_ret = seqlist_delete(list, &del_key, student_cmp);
  if (del_ret == 1) {
    printf("删除成功！剩余元素数：%d\n", seqlist_size(list));
    printf("删除后元素列表：\n");
    seqlist_traval(list, student_print); // 预期剩余：101、104、102（已更新）
  } else {
    printf("删除失败！\n");
  }

  // -------------------------- 测试7：排序（按ID升序）
  // --------------------------
  printf("\n=== 测试7：排序（按学生ID升序）===\n");
  int sort_ret = seqlist_qsort(list->arr, seqlist_size(list), sizeof(Student),
                               student_cmp);
  if (sort_ret == 1) {
    printf("排序成功！排序后元素列表：\n");
    seqlist_traval(list, student_print); // 预期顺序：101 → 102 → 104
  } else {
    printf("排序失败！\n");
  }

  // -------------------------- 测试8：反转顺序表 --------------------------
  printf("\n=== 测试8：反转顺序表 ===\n");
  int reverse_ret = seqlist_reverse(list);
  if (reverse_ret == 1) {
    printf("反转成功！反转后元素列表：\n");
    seqlist_traval(list, student_print); // 预期顺序：104 → 102 → 101
  } else {
    printf("反转失败！\n");
  }

  // -------------------------- 测试9：清空与容量调整 --------------------------
  printf("\n=== 测试9：清空与容量调整 ===\n");
  // 9.1 清空元素
  seqlist_clear(list);
  printf("清空后元素数：%d（容量不变：%d）\n", seqlist_size(list),
         seqlist_capacity(list));

  // 9.2 调整容量（缩小到2）
  int resize_ret = seqlist_resize(&list, 2);
  if (resize_ret == 1) {
    printf("容量调整成功！新容量：%d\n", seqlist_capacity(list));
  } else {
    printf("容量调整失败！\n");
  }

  // -------------------------- 测试10：异常场景（空表操作）
  // --------------------------
  printf("\n=== 测试10：异常场景（空表删除）===\n");
  int err_del = seqlist_delete(list, &del_key, student_cmp);
  if (err_del == -1) {
    printf("空表删除测试：符合预期（返回-1，删除失败）\n");
  }

  // -------------------------- 测试11：销毁顺序表 --------------------------
  printf("\n=== 测试11：销毁顺序表 ===\n");
  seqlist_destory(&list);
  if (list == NULL) {
    printf("销毁成功！顺序表指针已置空\n");
  }

  printf("\n==================== 所有测试完成 ====================\n");
  return;
}
